home *** CD-ROM | disk | FTP | other *** search
/ Otherware / Otherware_1_SB_Development.iso / mac / developm / source / ncsat.cpt / Telnet2.5 final / main / ftpbin.c < prev    next >
Encoding:
C/C++ Source or Header  |  1992-04-05  |  58.8 KB  |  1,987 lines

  1. /*
  2. *  User FTP
  3. *  6/8/87
  4. ****************************************************************************
  5. *                                                                          *
  6. *      by Tim Krauskopf and Swami Natarajan                                *
  7. *                                                                          *
  8. *      National Center for Supercomputing Applications                     *
  9. *      152 Computing Applications Building                                 *
  10. *      605 E. Springfield Ave.                                             *
  11. *      Champaign, IL  61820                                                *
  12. *                                                                          *
  13. *                                                                          *
  14. ****************************************************************************
  15. */
  16. #include <stdio.h>
  17. #include <stdlib.h>
  18. #include <ctype.h>
  19. #include <string.h>
  20. #include <strings.h>
  21.  
  22. #include <Controls.h>
  23. #include <Desk.h>
  24. #include <Dialogs.h>
  25. #include <DiskInit.h>
  26. #include <Events.h>
  27. #include <Fcntl.h>
  28. #include <Files.h>
  29. #include <Fonts.h>
  30. #include <Menus.h>
  31. #include <Memory.h>
  32. #include <OSEvents.h>
  33. #include <OSUtils.h>
  34. #include <Packages.h>
  35. #include <Quickdraw.h>
  36. #include <Resources.h>
  37. #include <Script.h>
  38. #include <ToolUtils.h>
  39. #include <Windows.h>
  40.  
  41. #include "wind.h"
  42. #include "configrec.h"
  43. #include "hostform.h"
  44. #include "whatami.h"
  45. #include "VSkeys.h"
  46. #include "prefs.h"
  47. #include "user.h"
  48. #include "util.h"
  49. #include "bkgr.h"
  50. #include "maclook.h"
  51. #include "netevent.h"
  52. #include "vsinterf.h"
  53. #include "menu.h"
  54. #include "rsmac.h"
  55. #include "macbinary.h"
  56. #include "binsubs.h"
  57. #include "ser.h"        /* BYU 2.4.15 */
  58.  
  59. #include "ftppi.h"        /* list of commands, help strings */
  60.  
  61. #define MACBINARY
  62.  
  63. #define FASCII 0
  64. #define FIMAGE 1    /* This is different than the definition in bkgr.c */
  65. #define FAMODE 0
  66. #define FIMODE 1
  67. #define FMMODE 2    /* Mac Binary, when ready */
  68.  
  69. #define HFTP  21
  70.  
  71. #define FALSE       0
  72. #define TRUE       1
  73. #define SUCCESS       2
  74. #define ERROR      -1
  75. #define NONE      -2
  76. #define ABORT      -3
  77. #define INCOMPLETE -4
  78. #define AMBIGUOUS -5
  79. #define HAVEDATA   4
  80.  
  81. #define BUFFERS 8000    /* size of buffer */
  82. #define PATHLEN 256
  83. #define READSIZE 128    /* how much to read */
  84.  
  85. #define HELPRESID 23229
  86.  
  87. long
  88.     filelen=0,            /* file transfer length */
  89.     start=0L,            /* timing var */
  90.     towrite=0,            /* file transfer pointer */
  91.     translen=0,            /* length of file transfered */
  92.     transtime;
  93.  
  94. int 
  95.     xp=0,                /* general pointer */
  96.     ftpfh,                /* file handle for ftp */
  97.     fcnt = 0,            /* counter for ftpd */
  98.     ftpfilemode=0,        /* file open mode for transfer */
  99.     hash=0,                /* hash mark printing */
  100.     sendport=1,            /* to send ports or not */
  101.     verbose=1,            /* informative messages */
  102.     bell=0,                /* sound bell */
  103.     autologin=1,        /* login on connect */
  104.     prompt=1,            /* check on multiple commands */
  105.     glob=1,                /* expand wildcards */
  106.     slashflip=1,        /* change \ to / */
  107.     fromtty=1;            /* default input from tty */
  108.  
  109. static int ftpdata;
  110.  
  111. #ifdef PC
  112.  
  113. #define RCPSEGSIZE 1024
  114. #define EOLCHAR 10
  115.  
  116. #ifdef MSC
  117. #define O_RAW O_BINARY
  118. #endif
  119.  
  120. #else
  121.  
  122. extern char
  123.     *firstname(),
  124.     *nextname();
  125.  
  126. extern unsigned char SLIP_ip_number[];        /* BYU 2.4.15 */
  127.  
  128. extern int 
  129.     defaultv,                                /* BYU 2.4.18 */
  130.     ftpenable,
  131.     MacBinary,
  132.     chgdir(),
  133.     ftpdo(),
  134.     netputuev(),
  135.     Sfread(),
  136.     Sfwrite(),
  137.     WindByPort();
  138.  
  139. extern MBFile
  140.     *MBopen();
  141.  
  142. extern void 
  143.     GetFileInfo(),
  144.     setupport();
  145.  
  146. #define RCPSEGSIZE 512
  147. #define O_RAW O_RDONLY
  148. #define EOLCHAR 13
  149. #endif
  150.  
  151. FILE
  152.     *fromfp=NULL;            /* file pointer for input */
  153.  
  154. MBFile
  155.     *ftp_mbfp;
  156.  
  157. FileParam iop;
  158.  
  159. #define captlistsize 2001L
  160. unsigned char 
  161.     *captlist = 0L,
  162.     *newfile = 0L,
  163.     *transfile = 0L,        /* name of file being sent/received */
  164.     *xs = 0L;                /* response string */
  165.  
  166. unsigned int curftpprt = 0;    /* port to use */
  167.  
  168. unsigned char 
  169.     *neterrstring();
  170.  
  171. static char bellchar = { 7 };
  172. static char backspace = { 8 };
  173. static char poundsign = { '#' };
  174.  
  175. char response_data[20][4];            /* BYU 2.4.12 - first 4 characters of each response */
  176. unsigned char response_count[20];    /* BYU 2.4.12 - non-zero indicates waiting for response */
  177.  
  178. extern long JuggTicks;            /* How many ticks to wait when Juggling */
  179. extern int debug,ev,Juggling,scrn;
  180. extern WindRec *screens;
  181. extern char Sptypes[];            /* BYU 2.4.16 - flags for port #'s */
  182.  
  183. extern int netlisten();
  184.  
  185. /* Beginning of Macintosh Routines created at BYU, 1988 */
  186.  
  187. /************************************************************************/
  188. /* putstring: display string using vt100 emulation routines
  189. /************************************************************************/
  190.  
  191. putstring(ftpscrn,string) int ftpscrn; char *string; {
  192. for (; *string; string++) parse( &screens[ftpscrn],string,1);
  193. }
  194.  
  195. nputs(line) char *line; {
  196.   putln(line);
  197. }
  198.  
  199. char *stpblkp(mystring) char *mystring; {
  200. /* Return pointer to first non blank in string */
  201. int mycnt;
  202. char *p;
  203.   mycnt = 0;
  204.   p = mystring;
  205.   while (((*p == ' ') || (*p == '\t')) && (mycnt < 256)) {
  206.     p++;
  207.     mycnt++;
  208.   }
  209.   return(p);
  210. }
  211.  
  212. char *stptok(mystring,myword,mylen,myterms) char *mystring,*myword,*myterms; int mylen; {
  213. /* Return pointer to first non blank in string */
  214. int done,i;
  215. char *p,*q;
  216.  
  217.     p = stpblkp(mystring);            /* skip leading blanks */
  218.     i = 0;
  219.     done = 0;
  220.     while (*(p+i) && (i <= mylen) && (done == 0)) {
  221.       q = myterms;
  222.       while ((*q) && (*q != *(p+i))) q++;
  223.       if (!(*q)) {
  224.         *(myword+i) = *(p+i);
  225.         i++;
  226.       } else done = 1;
  227.     } 
  228.     *(myword+i) = '\0';
  229.     q = p+i;
  230.     return(q);
  231. }
  232.  
  233. int ftpopen(name) char *name; {
  234. int myerr;
  235. short myvrefnum,myrefnum;
  236. char volname[256];
  237.   GetVol(volname,&myvrefnum);
  238.   myerr = FSOpen(name,myvrefnum,&myrefnum);
  239.   return(myrefnum);
  240. }
  241.  
  242. int ftpcreate(name) char *name; {
  243. int myerr;
  244. short myvrefnum,myrefnum;
  245. char volname[256];
  246.   GetVol(volname,&myvrefnum);
  247.   myerr = Create(name,myvrefnum,'????','TEXT');
  248.   myerr = FSOpen(name,myvrefnum,&myrefnum);
  249.   return(myrefnum);
  250. }
  251.  
  252. /* End of Macintosh Routines created at BYU, 1988 */
  253.  
  254. /************************************************************************/
  255. /* ftpgets - read a line from the keyboard
  256. /*         returns ABORT if aborted, non-zero on success
  257. /************************************************************************/
  258.  
  259. ftpgets(s,lim,echo)
  260.     char *s;        /* where to put the line */
  261.     short lim,echo;        /* max chars to read, echo? */
  262.     {
  263.     int count,i,cmd_status;
  264.     unsigned char c;
  265.     char *save, *ret;
  266.     Boolean gotOne;            /* Did we get an event */
  267.     EventRecord myEvent;    /* Event Record for this loop */
  268.  
  269.     count = 0;        /* none read */
  270.     save = s;        /* beginning of line */
  271.  
  272.     if (!fromtty) {
  273.        if (fromfp==NULL) {
  274.         ret = fgets(s,lim,stdin);
  275.        }
  276.        else {
  277.         ret = fgets(s,lim,fromfp);
  278.        }
  279.        if (ret==NULL) {
  280.             nputs("EOF or error on read from file\012");
  281.             cmd_status = ftpdo(scrn,"QUIT","");
  282.             netclose(screens[scrn].port);
  283.             destroyport( scrn);
  284.             exit(1);
  285.        }
  286.        s[strlen(s)-1] = '\0';    /* remove newline */
  287.        if (echo && fromfp) nputs(s);
  288.        return (strlen(s));
  289.     }
  290.     while (1) {
  291.  
  292.         if (Juggling)
  293.             gotOne = WaitNextEvent(everyEvent, &myEvent, JuggTicks, 0L);
  294.         else
  295.             gotOne = GetNextEvent(everyEvent, &myEvent);
  296.  
  297.         if ((myEvent.what == keyDown) || (myEvent.what == autoKey))
  298.             c = myEvent.message & charCodeMask;
  299.         else {
  300.             DoModem();            /* BYU 2.4.15 */
  301.             Stask();            /* BYU 2.4.15 */
  302.             DoNetEvents();        /* process event queue */
  303.             c = 0;
  304.         }
  305.  
  306.         switch (c) {        /* allow certain editing chars */
  307.             case 8:        /* backspace */
  308.                 if (count) {
  309.                     if (echo) {
  310.                         parse( &screens[scrn],&c,1);
  311.                         parse( &screens[scrn]," ",1);
  312.                         parse( &screens[scrn],&c,1);
  313.                     }
  314.                     count--;    /* one less character */
  315.                     s--;        /* move pointer backward */
  316.                 }
  317.                 break;
  318.             case 13:        /* carriage return, = ok */
  319.                 if (echo) putstring(scrn,"\015\012");    /* newline */
  320.                 *s = '\0';    /* terminate the string */
  321.                 return(c);    /* return ok */
  322.                 break;
  323.             case 21:        /* kill line */
  324.                 for (i=0; i < s-save; i++) {    /* length of line */
  325.                     if (echo) {        /* erase */
  326.                         parse( &screens[scrn],&backspace,1);
  327.                         parse( &screens[scrn]," ",1);
  328.                         parse( &screens[scrn],&backspace,1);
  329.                     }
  330.                 }
  331.                 s = save;    /* reset line */
  332.                 break;
  333.             case 0:            /* do nothing */
  334.                 break;
  335.             default:        /* not special char */
  336.                 if (c > 31 && c < 127) {    /* printable */
  337.                     if (echo) parse( &screens[scrn],&c,1);    /* display */
  338.                     *s++ = c;    /* add to string */
  339.                     count++;    /* length of string */
  340.                 }
  341.                 else        /* acts as eol */
  342.                     return(c);    /* value of special char */
  343.  
  344.                 if (count == lim) {    /* to length limit */
  345.                     *s = '\0';    /* terminate */
  346.                     return(c);    
  347.                 }
  348.             break;
  349.         }
  350.  
  351.     }
  352. }
  353.  
  354. /************************************************************************/
  355. /* captcon
  356. *  capture everything from a connection into the capture list
  357. *  return -1 on closed connection, else 0, 1 if paused
  358. /************************************************************************/
  359.  
  360. captcon(cnum,mywindow) int cnum,mywindow; {
  361.     int capturesize,cnt = 0;
  362.     unsigned char s[80];                /* temporary string */
  363.  
  364. /*    if (fromtty && n_scrlck()) return(TRUE);    /* if paused, nothing to do */
  365.     capturesize = screens[mywindow].capturesize;
  366.     do {
  367.         cnt = netread(cnum,&s[0],64);    /* get some from queue */
  368.         if ((cnt + capturesize) < captlistsize) {
  369.             BlockMove(&s[0],&captlist[capturesize],(long)cnt);
  370.             capturesize += cnt;
  371.         }
  372.  
  373. /* demux all packets */
  374.     } while ((cnt > 0) && ((cnt + capturesize) < captlistsize));
  375.  
  376.     captlist[capturesize] = 0;
  377.     screens[mywindow].capturesize = capturesize;
  378.  
  379.     return(cnt);            /* 0 normally, -1 if connection closed */
  380. }
  381.  
  382.  
  383. /************************************************************************/
  384. /*  telnet
  385. *   filter telnet options on incoming data
  386. /************************************************************************/
  387.  
  388. telnet(port,cnt,s) int port,cnt; unsigned char *s; {
  389. register int i,mylen,myport;
  390. char printline[256];        /* line to display */
  391.  
  392.     myport = WindByPort(port);
  393.     for (i=0; i < cnt; i++) {            /* put on screen */
  394.         if (*(s+i) & 128) {                /* if over ASCII 128 */
  395.             sprintf(printline," %d ",*(s+i));    /* show as number */
  396.             mylen = strlen(printline);
  397.             parse( &screens[myport],&printline[0],mylen);
  398.         }
  399.         else
  400.             parse( &screens[myport],(s+i),1);
  401.     }
  402.     return(TRUE);        
  403. }
  404.  
  405.  
  406. /************************************************************************/
  407. /* dumpcon
  408. *  take everything from a connection and send it to the screen
  409. *  return -1 on closed connection, else 0, 1 if paused
  410. /************************************************************************/
  411.  
  412. int dumpcon(cnum,mywindow) int cnum,mywindow; {        /* BYU 2.4.12 */
  413.     short i1,i2,cnt = 0,result=0;                    /* BYU 2.4.12 */
  414.     unsigned char s1[64],s2[128];            /* temporary strings */
  415.  
  416. /*    if (fromtty && n_scrlck()) return(TRUE);    /* if paused, nothing to do */
  417.  
  418.     do {
  419.         cnt = netread(cnum,&s1[0],64);        /* get some from queue */
  420.  
  421. /* Search the incoming data for status codes and newlines */
  422.         i1 = 0;
  423.         i2 = 0;
  424.         while (i1 < cnt) {
  425.  
  426. /* Check for 3 digit codes beginning with "5" at the beginning of each line. */
  427.           if (s1[i1] == '\012' || s1[i1] == '\015') {        /* BYU 2.4.12 */
  428.               response_count[mywindow] = 0;                    /* BYU 2.4.12 */
  429.           } else if (response_count[mywindow] < 4) {                        /* BYU 2.4.12 */
  430.             response_data[mywindow][response_count[mywindow]++] = s1[i1];    /* BYU 2.4.12 */
  431.             if (response_count[mywindow] == 4) {                            /* BYU 2.4.12 */
  432.               if (response_data[mywindow][0] == '5' &&        /* BYU 2.4.12 */
  433.                   response_data[mywindow][1] >= '0' &&         /* BYU 2.4.12 */
  434.                   response_data[mywindow][1] <= '9' &&        /* BYU 2.4.12 */
  435.                   response_data[mywindow][2] == '0' &&         /* BYU 2.4.12 */
  436.                   response_data[mywindow][2] <= '9' &&        /* BYU 2.4.12 */
  437.                   response_data[mywindow][3] == ' ')        /* BYU 2.4.12 */
  438.                   result = -1;            /* BYU 2.4.12 - Abort indicated by other host */
  439.           } }
  440.  
  441. /* If a "newline" is found then force a "carriage return" immediately. */
  442.           if ('\012' == (s2[i2++] = s1[i1++]))
  443.             s2[i2++] = '\015';
  444.         }
  445.  
  446.         telnet(cnum,i2,&s2[0]);            /* display on screen, etc.*/
  447.  
  448. /* demux all packets */
  449.     } while (cnt > 0);
  450.  
  451.     return(result);            /* BYU 2.4.12 - 0 normally, -1 if connection closed */
  452. }
  453.  
  454.  
  455. /************************************************************************/
  456. /* getword: remove a word from a string.  Things within quotes are
  457. * assumed to be one word.
  458. * return TRUE on success, FALSE on end of string
  459. /************************************************************************/
  460.  
  461. getword(string,word) char *string,*word; {
  462. char *p,*q;
  463. int i=0;
  464.  
  465. p = stpblkp(string);            /* skip leading blanks */
  466. if (!(*p)) {                /* no words in string */
  467.     word[0] = '\0';
  468.     return(FALSE);
  469. }
  470. if (*p=='!') {                /* ! is a word */
  471.     word[0] = *p;
  472.     word[1] = '\0';
  473.     strcpy(string,++p);
  474.     return(TRUE);
  475. }
  476. if (*p=='\"') {                /* word delimited by quotes */
  477.     while (p[++i] && p[i]!='\"') word[i-1] = p[i];
  478.     word[i-1] = '\0';
  479.     if (!p[i]) nputs("Missing \". Assumed at end of string.");
  480.     else i++;
  481.     q = p+i;
  482. }
  483. else q = stptok(p, word, 50, " \t\015\012"); /* get word, max len 50 */
  484. p = stpblkp(q);                /* remove trailing blanks */
  485. strcpy(string,p);            /* remove extracted stuff */
  486. return(TRUE);
  487. }
  488.  
  489.  
  490. /************************************************************************/
  491. /* lowercase: convert a string to lowercase
  492. *
  493. /************************************************************************/
  494.  
  495. lowercase(word) char *word; {
  496. int i;
  497.  
  498. for (i=0; word[i]=tolower(word[i]); i++);
  499. return(TRUE);
  500. }
  501.  
  502.  
  503. /************************************************************************/
  504. /* finduniq: find name that is a unique prefix of one of the entries in
  505. * a list.  Return position of the entry, NONE if none, AMBIGUOUS if more
  506. * than one.
  507. *
  508. /************************************************************************/
  509.  
  510. int finduniq(name,listsize) unsigned char *name; int listsize; {
  511. int i,j=NONE,len;
  512. unsigned char *p,cmdstring[256];
  513.  
  514. len = strlen(name);
  515. for (i=0; i<listsize; i++) {
  516.     GetIndString(cmdstring,FTPCOMMANDS,i+1);
  517.     p = p2cstr(cmdstring);
  518.     if (!strncmp(name,cmdstring,len)) {        /* prefix */
  519.         if (len==strlen(cmdstring)) return(i+1);    /* exact match */
  520.         if (j!=NONE) j = AMBIGUOUS;            /* more than one match */
  521.         else j = i+1;                        /* note prefix found */
  522.     }
  523. }
  524. return(j);            /* prefix */
  525. }
  526.  
  527.  
  528. /************************************************************************/
  529. /* checkoredir: check for output redirection.  If the command contains a
  530. * >, assume a filename follows and extract it.  Remove the redirection
  531. * from the original command.
  532. * Also change \ to /
  533. * return TRUE if redirection specified, FALSE otherwise 
  534. /************************************************************************/
  535.  
  536. checkoredir(command,filename,slashflip)
  537. char *command,*filename;
  538. int slashflip;
  539. {
  540. int i;
  541.  
  542.   filename[0] = '\0';
  543.   for (i=0; (command[i]!='>'); i++) {    /* process command part */
  544.     if (slashflip && command[i] == '\\') command[i] = '/';
  545.         if (!command[i]) return(FALSE);    /* no redirection */
  546.   }
  547.   getword(&command[i+1],filename);    /* get redirected filename */
  548.   command[i] = '\0';
  549.   return(TRUE);
  550. }
  551.  
  552.  
  553. /************************************************************************/
  554. /* getnname: get next name from captured list
  555. * names delimited by newlines - <CR> or <LF>
  556. /************************************************************************/
  557.  
  558. getnname(string,word) char *string,*word; {
  559. char *s;
  560.  
  561. s = string;
  562. while ((*string=='\012') || (*string=='\015')) string++;    /* skip initial newlines */
  563. if (!(*string)) return(FALSE);        /* end of captlist */
  564. while ((*string!='\012') && (*string!='\015') && (*string)) *(word++) = *(string++);
  565. while ((*string=='\012') || (*string=='\015')) string++;    /* skip trailing newline */
  566. *word = '\0';
  567. strcpy(s,string);
  568. return(TRUE);
  569. }
  570.  
  571.  
  572. /********************************************************************/
  573. /* FTP PI
  574. *  Protocol interpreter for user interface commands
  575. *  Will permit any command to be abbreviated uniquely.
  576. *  Recognizes commands, translates them to the protocol commands to be
  577. *  sent to the other server, and uses userftpd, the daemon, to do data
  578. *  transfers.
  579. /************************************************************************/
  580.  
  581. ftppi(command) char *command; {
  582. Boolean needanswer;
  583. int cmdno,i,cmd_status;
  584. char cmdname[20],word[PATHLEN],line[MAXFTP],answer[20],ofilename[PATHLEN];
  585. char *p,*getWDname();
  586. unsigned char destname[50];    /* who to connect to */
  587. char printline[256];        /* line to display */
  588.  
  589.     if (captlist == 0) {
  590.         captlist = NewPtr( (long) captlistsize);
  591. /*        newfile = NewPtr( (long) PATHLEN);        /* Pointer, no allocation necessary */
  592.         transfile = NewPtr( (long) PATHLEN);
  593.         xs = NewPtr( (long) (BUFFERS+10));
  594.     }
  595.  
  596. /* Indicates waiting for response */            /* BYU 2.4.12 */
  597.     response_count[scrn] = 0;                    /* BYU 2.4.12 */
  598.  
  599. /* get command number */
  600. if (!getword(command,cmdname)) return(FALSE);    /* get command name */
  601.  
  602. /* removes first word from command */
  603. lowercase(cmdname);
  604. cmdno = finduniq(cmdname,NCMDS);    /* search cmdlist for prefix */
  605. if (cmdno==AMBIGUOUS) {        /* not unique abbreviation */
  606.     putstring(scrn,"?Ambiguous command\015\012");
  607.     return(FALSE);
  608. }
  609. if (cmdno==NONE) {        /* not a prefix of any command */
  610.     putstring(scrn,"?Invalid command\015\012");
  611.     return(FALSE);
  612. }
  613.  
  614.         /* change \ to / and check if command output redirected */
  615. if (cmdno!=BANG) {        /* don't alter shell escape */
  616.     if (cmdno!=LLS)        /* do not flip slashes for LLS */
  617.         checkoredir(command,ofilename,slashflip);    /* check redirection, flip \ */
  618.     else
  619.         checkoredir(command,ofilename,FALSE);        /* check redirection */
  620. }
  621.  
  622.     /* process commands */
  623. switch (cmdno) {
  624.     case QMARK:
  625.     case HELP:
  626.         if (!command[0]) {    /* no argument */
  627.             putstring(scrn,"Commands may be abbreviated:\015\012");
  628.  
  629.             /* display command list */
  630.             printline[0] = '\0';
  631.             for (i=2; i<NCMDS; i++) {
  632.                 GetIndString(word,FTPCOMMANDS,i+1);
  633.                 p = p2cstr(word);
  634.                 sprintf(word,"%-16s",word);    /* get word from list */
  635.                 strcat(printline,word);        /* add to line */
  636.                 if ((i-2)%5==4) {            /* display line */
  637.                     printline[79] = '\0';
  638.                     putstring(scrn,printline);
  639.                     putstring(scrn,"\015\012");
  640.                     printline[0] = '\0';
  641.                 }
  642.             }
  643.             if (i%5!=4) {
  644.                 putstring(scrn,printline);    /* last line */
  645.                 putstring(scrn,"\015\012");
  646.             }
  647.             return(TRUE);
  648.         }
  649.  
  650.             /* help for specific commands */
  651.         else {
  652.             while (getword(command,word)) {    /* loop for all args */
  653.                 i = finduniq(word,NCMDS);   /* which command? */
  654.                 if (i==AMBIGUOUS)    /* non-unique command name */
  655.                     sprintf(printline,"?Ambiguous help command %s",word);
  656.                 else if (i==NONE)    /* no such command */
  657.                     sprintf(printline,"?Invalid help command %s",word);
  658.                 else {            /* display help string */
  659.                     GetIndString(printline,HELPRESID,i);
  660.                     p = p2cstr(printline);
  661.                 }
  662.                 putstring(scrn,printline);
  663.                 putstring(scrn,"\015\012");
  664.             }
  665.             return(TRUE);
  666.         }
  667.         break;
  668.     case BANG:        /* shell escape */
  669. #if 0
  670.         if (*(stpblkp(command))) {    /* command specified */
  671.             system(command);    /* execute command */
  672.             return(TRUE);
  673.         }
  674.         dosescape();        /* subshell */
  675. #endif
  676.         return(TRUE);
  677.     case BELL:
  678.         if (getword(command,word)) {    /* scan arg */
  679.             lowercase(word);
  680.             if (!strcmp(word,"off")) bell = FALSE;
  681.             else if (!strcmp(word,"on")) bell = TRUE;
  682.             else bell = !bell;
  683.         }
  684.         else bell = !bell;
  685.         if (bell) nputs("Bell mode on.");
  686.         else nputs("Bell mode off.");
  687.         return(TRUE);
  688.     case BYE:
  689.     case QUIT:
  690.         cmd_status = ftpdo(scrn,"QUIT",ofilename);
  691.         netclose(screens[scrn].port);
  692.         destroyport( scrn);
  693.         return(TRUE);
  694.     case DEBUG:        /* turn on/off debugging, optional level */
  695.         if (debug) {
  696.             debug = 0;
  697.             nputs("Debug off");
  698.         } else {
  699.             debug = 1;
  700.             nputs("Debug on");
  701.         }
  702.         return(TRUE);
  703.     case GLOB:        /* wildcard expansion */
  704.         if (getword(command,word)) {
  705.             lowercase(word);
  706.             if (!strcmp(word,"off")) glob = FALSE;
  707.             else if (!strcmp(word,"on")) glob = TRUE;
  708.             else glob = !glob;
  709.         }
  710.         else glob = !glob;
  711.         if (glob) nputs("Globbing on.");
  712.         else nputs("Globbing off.");
  713.         return(TRUE);
  714.     case HASH:        /* hash mark printing */
  715.         if (getword(command,word)) {
  716.             lowercase(word);
  717.             if (!strcmp(word,"off")) hash = FALSE;
  718.             else if (!strcmp(word,"on")) hash = TRUE;
  719.             else hash = !hash;
  720.         }
  721.         else hash = !hash;
  722.         if (hash) nputs("Hash mark printing on (1024 bytes/hash mark).");
  723.         else nputs("Hash printing off.");
  724.         return(TRUE);
  725.     case INTERACTIVE:    /* prompting on multiple transfers */
  726.         prompt = TRUE;
  727.         putstring(scrn,"Interactive mode on.\015\012");
  728.         return(TRUE);
  729.     case LCD:        /* change local directory */
  730.         if (*(stpblkp(command))) {                        /* BYU 2.4.17 - CD */
  731.             getword(command,word);                        /* BYU 2.4.17 */
  732.             if (chgdir(word))                            /* BYU 2.4.17 */
  733.             putstring(scrn,"Unable to change directory\015\012");
  734.         }
  735.         p = getWDname();    /* current directory */
  736.         p = p2cstr(p);
  737.         sprintf(printline,"Local directory now %s\015\012",p);
  738.         putstring(scrn,printline);
  739.         return(TRUE);
  740.     case LDIR:        /* local DIR */
  741.     case LLS:
  742.         if (!(*(stpblkp(command)))) {            /* null response ok */
  743.             p = getWDname();    /* current directory */
  744.             p2cstr(p);
  745.             sprintf(line,"*");
  746.         } else {
  747.             p = command;
  748.             sprintf(line,"%s",command);
  749.         }
  750.         putstring(scrn,"Directory "); 
  751.         putstring(scrn,p);
  752.         putstring(scrn,"\015\012");
  753.         if (NULL == (newfile = firstname(&line[0]))) {
  754.             putstring(scrn,"No files found\015\012");
  755.         } else {
  756.             putstring(scrn,newfile);
  757.             putstring(scrn,"\015\012");
  758.             while (NULL != (newfile = nextname())) {
  759.                 putstring(scrn,newfile);
  760.                 putstring(scrn,"\015\012");
  761.         } }
  762.         return(TRUE);
  763.     case NONINTERACTIVE:    /* turn off interactive prompting */
  764.         prompt = FALSE;
  765.         nputs("Interactive mode off.");
  766.         return(TRUE);
  767.     case OPEN:        /* open connection to host */
  768.         setupport();        /* Open a connection */
  769.         return(TRUE);
  770.     case PROMPT:            /* interactive prompting */
  771.         if (getword(command,word)) {
  772.             lowercase(word);
  773.             if (!strcmp(word,"off")) prompt = FALSE;
  774.             else if (!strcmp(word,"on")) prompt = TRUE;
  775.             else prompt = !prompt;
  776.         }
  777.         else prompt = !prompt;
  778.         if (prompt) nputs("Interactive mode on.");
  779.         else nputs("Interactive mode off.");
  780.         return(TRUE);
  781.     case SENDPORT:            /* send PORT commands for each transfer */
  782.         if (getword(command,word)) {
  783.             lowercase(word);
  784.             if (!strcmp(word,"off")) sendport = FALSE;
  785.             else if (!strcmp(word,"on")) sendport = TRUE;
  786.             else sendport = !sendport;
  787.         }
  788.         else sendport = !sendport;
  789.         if (sendport) nputs("Use of PORT cmds on.");
  790.         else nputs("Use of PORT cmds off.");
  791.         return(TRUE);
  792.     case SLASHFLIP:            /* change \ to / */
  793.         if (getword(command,word)) {
  794.             lowercase(word);
  795.             if (!strcmp(word,"off")) slashflip = FALSE;
  796.             else if (!strcmp(word,"on")) slashflip = TRUE;
  797.             else slashflip = !slashflip;
  798.         }
  799.         else slashflip = !slashflip;
  800.         if (slashflip) nputs("Slash translation on.");
  801.         else nputs("Slash translation off.");
  802.         return(TRUE);
  803.     case STATUS:        /* display status info */
  804.         sprintf(printline,"Connected to %s",destname);
  805.         nputs(printline);
  806.         if (ftpfilemode==FASCII) nputs("Transfer mode is ascii.");
  807.         else nputs("Transfer mode is binary.");
  808.         if (bell) nputs("Bell on."); else nputs("Bell off.");
  809.         if (debug) {
  810.             nputs("Debug on");
  811.         }
  812.         else nputs("Debug off");
  813.         if (glob) nputs("Filename globbing on."); else nputs("Filename globbing off.");
  814.         if (hash) nputs("Hash-mark printing on."); else nputs("Hash-mark printing off.");
  815.         if (prompt) nputs("Interactive prompting on."); else nputs("Interactive prompting off.");
  816.         if (sendport) nputs("Sending of port commands on."); else nputs("Sending of PORT cmds off.");
  817.         if (slashflip) nputs("Flipping \\ to / on."); else nputs("Flipping \\ to / off.");
  818.         if (verbose) nputs("Verbose mode on."); else nputs("Verbose mode off.");
  819.  
  820.         nputs("\012Remote status:");
  821.         cmd_status = ftpdo(scrn,"STAT",ofilename);
  822.  
  823.         return(TRUE);
  824.     case VERBOSE:        /* display informative messages */
  825.         if (getword(command,word)) {
  826.             lowercase(word);
  827.             if (!strcmp(word,"off")) verbose = FALSE;
  828.             else if (!strcmp(word,"on")) verbose = TRUE;
  829.             else verbose = !verbose;
  830.         }
  831.         else verbose = !verbose;
  832.         if (verbose) nputs("Verbose mode on.");
  833.         else nputs("Verbose mode off.");
  834.         return(TRUE);
  835.     default:        /* The other commands valid only if connected (we always are here) */
  836.       switch (cmdno) {
  837.       case ACCT:            /* get file in binary mode */
  838.         while (!(*(stpblkp(command)))) {
  839.             putstring(scrn,"Acct: ");
  840.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  841.         }
  842.         sprintf(line,"ACCT %s",command);
  843.         cmd_status = ftpdo(scrn,line,ofilename);        /* get file */
  844.         return(TRUE);
  845.       case ASCII:            /* transfer mode */
  846.         cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  847.         return(TRUE);
  848.       case MACB:            /* transfer mode */
  849.           if (MacBinary) {
  850.             MacBinary = 0;
  851.             cmd_status = ftpdo(scrn,"MACB D",ofilename);
  852.         } else {
  853.             MacBinary = 1;
  854.             cmd_status = ftpdo(scrn,"MACB E",ofilename);
  855.         }
  856.         return(TRUE);
  857.       case BGET:            /* get file in binary mode */
  858.         i = ftpfilemode;    /* save current mode */
  859.         if (i==FASCII) cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  860.         while (!(*(stpblkp(command)))) {
  861.             putstring(scrn,"File: ");
  862.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  863.         }
  864.         sprintf(line,"RETR %s",command);
  865.         cmd_status = ftpdo(scrn,line,ofilename);        /* get file */
  866.         if (i==FASCII) cmd_status = ftpdo(scrn,"TYPE A",ofilename);    /* restore mode */
  867.         return(TRUE);
  868.       case BINARY:        /* binary mode */
  869.         cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  870.         return(TRUE);
  871.       case BPUT:            /* put file in binary mode */
  872.         i = ftpfilemode;
  873.         if (i==FASCII) cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  874.         while (!(*(stpblkp(command)))) {        /* if no arg */
  875.             putstring(scrn,"File: ");    /* get from user */
  876.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  877.         }
  878.         sprintf(line,"STOR %s",command);
  879.         cmd_status = ftpdo(scrn,line,ofilename);
  880.         if (i==FASCII) cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  881.         return(TRUE);
  882.       case CD:        /* change remote directory */
  883.         while (!(*(stpblkp(command)))) {        /* if no arg, get from user */
  884.             putstring(scrn,"To: ");
  885.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  886.         }
  887.         getword(command,word);
  888.         if (!strcmp(word,"..")) {    /* special case */
  889.             cmd_status = ftpdo(scrn,"CDUP",ofilename);
  890.             if (cmd_status!=ERROR) return(TRUE);        /* if CDUP understood */
  891. #if 0
  892.             nputs("Trying again...");
  893.             cmd_status = ftpdo(scrn,"XCUP",ofilename);    /* try alternative */
  894.             if (cmd_status!=ERROR) return(TRUE);
  895.             nputs("Trying again...");        /* else try usual CD */
  896. #endif
  897.         }
  898.         sprintf(line,"CWD %s",word);        /* try CWD */
  899.         cmd_status = ftpdo(scrn,line,ofilename);
  900.         if (cmd_status!=ERROR) return(TRUE);
  901. #if 0
  902.         nputs("Trying again...");
  903.         sprintf(line,"XCWD %s",word);        /* try XCWD */
  904.         cmd_status = ftpdo(scrn,line,ofilename);
  905. #endif
  906.         return(TRUE);
  907.       case CLOSE:                /* drop connection */
  908.         cmd_status = ftpdo(scrn,"QUIT",ofilename);
  909.         netclose(screens[scrn].port);
  910.         destroyport( scrn);
  911.         return(TRUE);
  912.       case DEL:
  913.       case RM:
  914.         getword(command,word);
  915.         while (!word[0]) {    /* get arg from user */
  916.             putstring(scrn,"File: ");
  917.             if (ftpgets(word,100,1)==ABORT) return(FALSE);    /* abort */
  918.         }
  919.         if (prompt) {        /* check interactively */
  920.             sprintf(printline,"Delete %s? ",word);
  921.             putstring(scrn,printline);
  922.             ftpgets(answer,20,1);
  923.             if (tolower(*(stpblkp(answer)))!='y') return(TRUE);
  924.         }
  925.         sprintf(line,"DELE %s",word);
  926.         cmd_status = ftpdo(scrn,line,ofilename);
  927.         return(TRUE);
  928.       case DIR:        /* get list of remote files */
  929.         if (ftpfilemode==FIMAGE) {
  930.             cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  931.             if (getword(command,word)) {
  932.                 sprintf(line,"LIST %s",word);
  933.             } else sprintf(line,"LIST");
  934.             strcpy(screens[scrn].ftpbuf,line);
  935.             screens[scrn].clientflags = TYPE_I_ON_CLOSE;
  936.             screens[scrn].ftpstate = 3;        /* Do "LIST" when "TYPE" is finished */
  937.             screens[scrn].ftpnext = 1;
  938.         } else {
  939.             if (getword(command,word)) {    /* Do DIR */
  940.                 sprintf(line,"LIST %s",word);
  941.                 cmd_status = ftpdo(scrn,line,ofilename);
  942.             } else cmd_status = ftpdo(scrn,"LIST",ofilename);
  943.         }
  944.         return(TRUE);
  945.       case GET:
  946.       case RECV:        /* get remote file */
  947.         while (!(*(stpblkp(command)))) {        /* if no arg */
  948.             putstring(scrn,"File: ");
  949.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  950.         }
  951.         sprintf(line,"RETR %s",command);
  952.         cmd_status = ftpdo(scrn,line,ofilename);
  953.         return(TRUE);
  954.       case LS:        /* get remote file list - short */
  955.         if (ftpfilemode==FIMAGE) {
  956.             cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  957.             if (getword(command,word)) {
  958.                 sprintf(line,"NLST %s",word);
  959.             } else sprintf(line,"NLST");
  960.             strcpy(screens[scrn].ftpbuf,line);
  961.             screens[scrn].clientflags = TYPE_I_ON_CLOSE;
  962.             screens[scrn].ftpstate = 3;        /* Do "NLST" when "TYPE" is finished */
  963.             screens[scrn].ftpnext = 1;
  964.         } else {
  965.             if (getword(command,word)) {
  966.                 sprintf(line,"NLST %s",word);
  967.                 cmd_status = ftpdo(scrn,line,ofilename);
  968.             } else cmd_status = ftpdo(scrn,"NLST",ofilename);
  969.         }
  970.         return(TRUE);
  971.       case MDELETE:
  972.         while (!(*(stpblkp(command)))) {        /* no arg */
  973.             putstring(scrn,"Files: ");
  974.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  975.         }
  976.         while (getword(command,word)) {        /* for each arg */
  977.             if (glob) {        /* wildcard expansion */
  978.                 sprintf(line,"NLST %s",word);
  979.                 screens[scrn].clientflags |= CAPTURE_DATA;
  980.                 cmd_status = ftpdo(scrn,line,ofilename);    /* put exapnsion in captlist */
  981.             }
  982.             else strcpy(captlist,word);    /* captlist has name(s) now */
  983.             while (getnname(captlist,word)) {    /* for each name */
  984.                 if (prompt) {    /* check */
  985.                 sprintf(printline,"mdelete %s? ",word);
  986.                 putstring(scrn,printline);
  987.                 if (ftpgets(answer,20,1)==ABORT) {    /* abort */
  988.                 command[0] = '\0';    /* no more processing */
  989.                 break;            /* quit immediately */
  990.                 }
  991.                 if (tolower(*(stpblkp(answer)))!='y') continue;
  992.                 }
  993.                 sprintf(line,"DELE %s",word);    /* delete */
  994.                 cmd_status = ftpdo(scrn,line,ofilename);
  995.             }
  996.         }
  997.         return(TRUE);
  998.       case MDIR:        /* remote multiple DIR */
  999.         i = ftpfilemode;    /* save mode */
  1000.         if (i==FIMAGE) cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  1001.         while (!(*(stpblkp(command)))) {        /* no arg */
  1002.             putstring(scrn,"Directories: ");
  1003.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  1004.         }
  1005.         while (getword(command,word)) {        /* for each arg */
  1006.             if (glob) {        /* expand wildcards */
  1007.                 sprintf(line,"NLST %s",word);
  1008.                 screens[scrn].clientflags |= CAPTURE_DATA;
  1009.                 cmd_status = ftpdo(scrn,line,ofilename);
  1010.             }
  1011.             else strcpy(captlist,word);
  1012.             while (getnname(captlist,word)) {    /* for each name */
  1013.                 if (prompt) {    /* check */
  1014.                 sprintf(printline,"mdir %s? ",word);
  1015.                 putstring(scrn,printline);
  1016.                 if (ftpgets(answer,20,1)==ABORT) {    /* abort */
  1017.                 command[0] = '\0';    /* no more processing */
  1018.                 break;            /* quit immediately */
  1019.                 }
  1020.                 if (tolower(*(stpblkp(answer)))!='y') continue;
  1021.                 }
  1022.                 sprintf(line,"LIST %s",word);    /* DIR */
  1023.                 cmd_status = ftpdo(scrn,line,ofilename);
  1024.             }
  1025.         }
  1026.         if (i==FIMAGE) cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  1027.         return(TRUE);
  1028.       case MGET:                            /* get multiple files */
  1029.         getword(command,line);
  1030.         while (!line[0]) {                    /* no arg */
  1031.             putstring(scrn,"Files: ");
  1032.             if (ftpgets(line,100,1)==ABORT) return(FALSE);    /* abort */
  1033.         }
  1034.         if (getword(line,word)) {
  1035.             sprintf(command,"NLST %s",word);
  1036.             screens[scrn].clientflags |= CAPTURE_DATA;
  1037.             cmd_status = ftpdo(scrn,command,ofilename);
  1038.  
  1039.             screens[scrn].clientflags |= MGET_STATE;
  1040.         }
  1041.         return(TRUE);
  1042.       case MKDIR:                            /* create directory */
  1043.         while (!(*(stpblkp(command)))) {        /* no arg */
  1044.             putstring(scrn,"Directory: ");
  1045.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  1046.         }
  1047.         sprintf(line,"XMKD %s",command);    /* try XMKD */
  1048.         cmd_status = ftpdo(scrn,line,ofilename);
  1049.             if (cmd_status!=ERROR) return(TRUE);
  1050.         nputs("Trying again...");
  1051.         sprintf(line,"MKD %s",command);        /* else try MKD */
  1052.         cmd_status = ftpdo(scrn,line,ofilename);
  1053.         return(TRUE);
  1054.       case MLS:
  1055.         i = ftpfilemode;
  1056.         if (i==FIMAGE) cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  1057.         while (!(*(stpblkp(command)))) {        /* no arg */
  1058.             putstring(scrn,"Directories: ");
  1059.             if (ftpgets(command,100,1)==ABORT) return(FALSE);    /* abort */
  1060.         }
  1061.         while (getword(command,word)) {        /* for each arg */
  1062.             if (glob) {        /* exapnd wildcards */
  1063.                 sprintf(line,"NLST %s",word);
  1064.                 screens[scrn].clientflags |= CAPTURE_DATA;
  1065.                 cmd_status = ftpdo(scrn,line,ofilename);
  1066.             }
  1067.             else strcpy(captlist,word);
  1068.             while (getnname(captlist,word)) {    /* for each name */
  1069.                 if (prompt) {        /* check */
  1070.                 sprintf(printline,"mls %s? ",word);
  1071.                 putstring(scrn,printline);
  1072.                 if (ftpgets(answer,20,1)==ABORT) {  /* abort */
  1073.                 command[0] = '\0';    /* no more processing */
  1074.                 break;            /* quit immediately */
  1075.                 }
  1076.                 if (tolower(*(stpblkp(answer)))!='y') continue;
  1077.                 }
  1078.                 sprintf(line,"NLST %s",word);    /* DIR */
  1079.                 cmd_status = ftpdo(scrn,line,ofilename);
  1080.             }
  1081.         }
  1082.         if (i==FIMAGE) cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  1083.         return(TRUE);
  1084.       case MODE:        /* set stream mode */
  1085.         getword(command,word);
  1086.         lowercase(word);
  1087.         if (strncmp(word,"stream",strlen(word)))
  1088.             nputs("We only support stream mode, sorry.");
  1089.         else nputs("Mode is stream.");
  1090.         return(TRUE);
  1091.       case MPUT:        /* put multiple files */
  1092.         getword(command,captlist);
  1093.         while (!captlist[0]) {    /* no arg */
  1094.             putstring(scrn,"Files: ");
  1095.             if (ftpgets(captlist,100,1)==ABORT) return(FALSE);    /* abort */
  1096.         }
  1097.         if (getword(captlist,transfile)) {        /* for each arg */
  1098.           newfile = NULL;
  1099.           needanswer = TRUE;
  1100.           while (needanswer) {
  1101.             needanswer = FALSE;
  1102.             if (glob) {                                /* local wildcard expansion */
  1103.                 if (newfile == NULL) {                /* if no expansions yet */
  1104.                     newfile = firstname(transfile);    /* get first name */
  1105.                     if (newfile == NULL) {            /* if no expansions */
  1106.                         sprintf(printline,"No match for %s",transfile);
  1107.                         nputs(printline);
  1108.                         if (getword(captlist,transfile)) {
  1109.                             needanswer = TRUE;
  1110.                     }    }
  1111.                 } else {                            /* not first name */
  1112.                     newfile = nextname(transfile);    /* get next name */
  1113.                     if (newfile == NULL) {            /* if no names, next arg */
  1114.                         if (getword(captlist,transfile)) {
  1115.                             needanswer = TRUE;
  1116.                 }    }    }
  1117.             } else newfile = transfile;                /* no expansion */
  1118.             if (newfile != NULL) {
  1119. #if 1    /* When prompting is fixed switch to the code below */
  1120.                 sprintf(command,"STOR \"%s\"",newfile);    /* name may have spl chars */
  1121.                 cmd_status = ftpdo(scrn,command,ofilename);
  1122.                 screens[scrn].clientflags |= MPUT_STATE;
  1123. #else
  1124.                 if (prompt) {                        /* check */
  1125.                     sprintf(printline,"mput %s? ",newfile);
  1126.                     putstring(scrn,printline);
  1127.                     if (ftpgets(answer,20,1)==ABORT) {    /* abort */
  1128.                         command[0] = '\0';                /* no more processing */
  1129.                         break;
  1130.                     } else if (tolower(*(stpblkp(answer))) == 'y') {
  1131.                         sprintf(command,"STOR \"%s\"",newfile);    /* name may have spl chars */
  1132.                         cmd_status = ftpdo(scrn,command,ofilename);
  1133.                         screens[scrn].clientflags |= MPUT_STATE;
  1134.                     }
  1135.                 } else {
  1136.                     sprintf(command,"STOR \"%s\"",newfile);    /* name may have spl chars */
  1137.                     cmd_status = ftpdo(scrn,command,ofilename);
  1138.                     screens[scrn].clientflags |= MPUT_STATE;
  1139.                 }
  1140. #endif
  1141.         } } }
  1142.         return(TRUE);
  1143.       case PUT:            
  1144.       case SEND:        /* put file */
  1145.         while (!(*(stpblkp(command)))) {        /* no args */
  1146.             putstring(scrn,"File: ");
  1147.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1148.         }
  1149.         sprintf(line,"STOR %s",command);    /* put file */
  1150.         cmd_status = ftpdo(scrn,line,ofilename);
  1151.         return(TRUE);
  1152.       case PWD:
  1153. #if 0
  1154.         cmd_status = ftpdo(scrn,"XPWD",ofilename);        /* try XPWD */
  1155.             if (i!=ERROR) return(TRUE);
  1156.         nputs("Trying again...");
  1157. #endif
  1158.         cmd_status = ftpdo(scrn,"PWD",ofilename);            /* else try PWD */
  1159.         return(TRUE);
  1160.       case QUOTE:
  1161.         while (!(*(stpblkp(command)))) {        /* no arg */
  1162.             putstring(scrn,"Command: ");
  1163.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1164.         }
  1165.         cmd_status = ftpdo(scrn,command,ofilename);        /* send command */
  1166.         return(TRUE);
  1167.       case REMOTEHELP:                /* get help */
  1168.         if (*(stpblkp(command))) {        /* for specific command */
  1169.             sprintf(line,"HELP %s",command);
  1170.             cmd_status = ftpdo(scrn,line,ofilename);
  1171.         }
  1172.         else cmd_status = ftpdo(scrn,"HELP",ofilename);        /* generic help */
  1173.         return(TRUE);
  1174.       case RENAME:        /* rename remote file */
  1175.         while (!(*(stpblkp(command)))) {        /* no arg */
  1176.             putstring(scrn,"From: ");
  1177.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1178.         }
  1179.         getword(command,word);
  1180.         sprintf(line,"RNFR %s",word);
  1181.         cmd_status = ftpdo(scrn,line,ofilename);        /* send rename from name */
  1182.         while (!(*(stpblkp(command)))) {        /* no second arg */
  1183.             putstring(scrn,"To: ");
  1184.             if (ftpgets(command,100,1)==ABORT) {
  1185.             cmd_status = ftpdo(scrn,"ABOR",ofilename);
  1186.             return(FALSE);
  1187.             }
  1188.         }
  1189.         sprintf(line,"RNTO %s",command); /* send rename to name */
  1190.         cmd_status = ftpdo(scrn,line,ofilename);
  1191.         return(TRUE);
  1192.       case RMDIR:            /* remove remote dir */
  1193.         while (!(*(stpblkp(command)))) {        /* no arg */
  1194.             putstring(scrn,"Directory: ");
  1195.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1196.         }
  1197.         sprintf(line,"XRMD %s",command);    /* try XRMD */
  1198.         cmd_status = ftpdo(scrn,line,ofilename);
  1199.             if (cmd_status!=ERROR) return(TRUE);
  1200.         nputs("Trying again...");
  1201.         sprintf(line,"RMD %s",command);        /* try RMD */
  1202.         cmd_status = ftpdo(scrn,line,ofilename);
  1203.         return(TRUE);
  1204.       case STRUCT:        /* set structure type - only file */
  1205.         getword(command,word);
  1206.         lowercase(word);
  1207.         if (strncmp(word,"file",strlen(word)))
  1208.             nputs("We only support file structure, sorry.");
  1209.         else nputs("Structure is file.");
  1210.         return(TRUE);
  1211.       case TYPE:        /* set transfer type */
  1212.         if (!getword(command,word)) {    /* no arg, just show */
  1213.            if (ftpfilemode==FASCII) nputs("Transfer type is ascii.");
  1214.            else nputs("Transfer type is binary.");
  1215.         }
  1216.         lowercase(word);
  1217.         if (!strncmp(word,"ascii",strlen(word)))
  1218.             cmd_status = ftpdo(scrn,"TYPE A",ofilename);
  1219.         else if (!strncmp(word,"binary",strlen(word)) ||
  1220.             !strncmp(word,"image",strlen(word)))
  1221.             cmd_status = ftpdo(scrn,"TYPE I",ofilename);
  1222.         else {
  1223.             sprintf(printline,"Unrecognized type: %s",word);
  1224.             nputs(printline);
  1225.         }
  1226.         return(TRUE);
  1227.       case USER:            /* login to remote machine */
  1228.         if (!(*(stpblkp(command)))) {    /* null response to prompt ok */
  1229.             putstring(scrn,"Username: ");
  1230.             if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1231.         }
  1232.         sprintf(line,"USER %s",command);    /* username */
  1233.         if ((cmd_status = ftpdo(scrn,line,ofilename))==TRUE) return(TRUE);
  1234. #if 0
  1235.         putstring(scrn,"Password: ");
  1236. #endif
  1237.         if (ftpgets(word,PATHLEN,0)==ABORT) return(FALSE);        /* no echoing */
  1238.         sprintf(line,"PASS %s",word);        /* password */
  1239.         if ((cmd_status = ftpdo(scrn,line,ofilename))==INCOMPLETE) {    /* if account needed */
  1240.             do {
  1241.                 putstring(scrn,"Account: ");
  1242.                 if (ftpgets(command,100,1)==ABORT) return(FALSE);
  1243.             } while (!(*(stpblkp(command))));
  1244.             sprintf(line,"ACCT %s",command);
  1245.             cmd_status = ftpdo(scrn,line,ofilename);
  1246.         }
  1247.         return(TRUE);        
  1248.     default:    /* unknown command */
  1249.         putstring(scrn,"?Invalid command\015\012");
  1250. #if 0
  1251.         sprintf(printline,"***Unknown command no: %d",cmdno);
  1252.         nputs(printline);
  1253. #endif
  1254.         break;
  1255.     }
  1256.     }
  1257. }
  1258.  
  1259.  
  1260. /************************************************************************/
  1261. /*   ftpport
  1262. *   return a new port number so that we don't try to re-use ports
  1263. *   before the mandatory TCP timeout period.  (lifetime of a packet)
  1264. *   use a time-based initial port selection scheme.
  1265. /************************************************************************/
  1266.  
  1267. ftpport(ftpscrn) int ftpscrn; {
  1268.     unsigned int i;
  1269.     unsigned char hostnum[5];
  1270.     char sendline[60];        /* for port command */
  1271. #if 0
  1272.     char printline[MAXFTP];        /* Debug - line to display */
  1273. #endif
  1274.  
  1275.     if (!sendport) {        /* default port */
  1276.         return(HFTP-1);
  1277.     }
  1278.     if (curftpprt < 40000) {    /* restart cycle */
  1279.         i = (unsigned int) TickCount();
  1280.         curftpprt = 40000 + (i & 0x3fff);
  1281.     }
  1282.  
  1283.     i = curftpprt--;    /* get port, update for next time */
  1284.  
  1285.     if (screens[ftpscrn].connectionType) {                            /* BYU 2.4.15 */
  1286.         hostnum[0] = SLIP_ip_number[0];                                /* BYU 2.4.15 */
  1287.         hostnum[1] = SLIP_ip_number[1];                                /* BYU 2.4.15 */
  1288.         hostnum[2] = SLIP_ip_number[2];                                /* BYU 2.4.15 */
  1289.         hostnum[3] = SLIP_ip_number[3];                                /* BYU 2.4.15 */
  1290.     } else                                                            /* BYU 2.4.15 */
  1291.         netgetip(hostnum);    /* get my ip number */                    /* BYU 2.4.15 */
  1292.  
  1293.     ftpdata = netlisten(i);
  1294.     screens[ftpscrn].ftpport = ftpdata;
  1295.     Sptypes[ftpdata] = UDATA;
  1296.  
  1297. #if 0
  1298. if (debug) {
  1299.     sprintf(printline,"ftpport port: %d  ftpdata: %d",i,ftpdata);
  1300.     nputs(printline);
  1301. }
  1302. #endif
  1303.  
  1304.     sprintf(sendline,"PORT %d,%d,%d,%d,%d,%d\015\012",hostnum[0],hostnum[1],hostnum[2],
  1305.         hostnum[3],i/256,i&255);    /* full port number */
  1306.  
  1307.     netpush(screens[ftpscrn].port);    /* empty command connection */
  1308.     netwrite(screens[ftpscrn].port,sendline,strlen(sendline));    /* send PORT command */
  1309.  
  1310.     return(i);        /* port number */
  1311.  
  1312. }
  1313.  
  1314.  
  1315. /************************************************************************/
  1316. /* ftpdo
  1317. *  Do whatever command is sent from the user interface using
  1318. *  userftpd, the background file handler
  1319. /************************************************************************/
  1320.  
  1321. int ftpdo(ftpscrn,s,ofile) int ftpscrn; char *s,*ofile; {
  1322.     int i;
  1323.     char name[MAXFTP],name2[MAXFTP];
  1324.     char commandbuf[MAXFTP];
  1325. #if 0
  1326.     char printline[MAXFTP];        /* Debug - line to display */
  1327.  
  1328.     nputs("FTPDO - begin");
  1329. #endif
  1330.  
  1331.     strcpy(commandbuf,s);
  1332.     for (i=0; i<4; i++) {
  1333.         commandbuf[i] = toupper(commandbuf[i]);    /* command to upper case */
  1334.     }
  1335.  
  1336.     if (!strncmp(commandbuf,"STOR",4)) {    /* put file */
  1337.         getword(&commandbuf[5],name);    /* first arg - local file */
  1338.         if (!commandbuf[5]) strcpy(&commandbuf[5],name);        /* if only one argument */
  1339.             else {
  1340.             getword(&commandbuf[5],name2);    /* second arg - removes quotes etc. */
  1341.             strcpy(&commandbuf[5],name2);    /* copy back into command */
  1342.         }
  1343.  
  1344. #ifdef MACBINARY
  1345.         if ((ftp_mbfp = MBopen( &name[0], defaultv, MB_READ + (((!MacBinary) ||    /* BYU 2.4.18 */
  1346.             (ftpfilemode == FAMODE)) ? MB_DISABLE : 0))) == 0L) {
  1347.             putstring(ftpscrn,"Could not open file\015\012");
  1348.             return(-1);
  1349.         }
  1350.         ftpfh = 12;
  1351. #else
  1352.         if (0 > (ftpfh = open(&name[0],ftpfilemode))) {
  1353.             putstring(ftpscrn,"Could not open file\015\012");
  1354.             return(-1);
  1355.         }
  1356. #endif
  1357.  
  1358.         c2pstr(&name[0]);
  1359.         GetFileInfo(0,&name[0],&iop);
  1360.         filelen = iop.ioFlLgLen;
  1361.         if (MacBinary && (ftpfilemode == FIMODE)) filelen += iop.ioFlRLgLen;
  1362.  
  1363.         ftpport(ftpscrn);        /* open data connection */
  1364.         screens[ftpscrn].ftpstate = 2;
  1365.         screens[ftpscrn].ftpnext = 20;
  1366.         strcpy(screens[ftpscrn].ftpbuf,commandbuf);
  1367.         strcat(screens[ftpscrn].ftpbuf,"\015\012");
  1368.         return(1);
  1369.  
  1370.     }
  1371.     else if (!strncmp(commandbuf,"RETR",4)) {    /* get file */
  1372.         getword(&commandbuf[5],name);            /* remote file */
  1373.         if (commandbuf[5]) {        /* two args present */
  1374.             getword(&commandbuf[5],name2);    /* local file */
  1375.  
  1376. #ifdef MACBINARY
  1377.                 if ((ftp_mbfp = MBopen(&name2[0], defaultv, MB_WRITE +    /* BYU 2.4.18 */
  1378.                     (((!MacBinary) || (ftpfilemode == FAMODE)) ? MB_DISABLE : 0
  1379.                     ))) == 0L) {
  1380.                     putstring(ftpscrn,"Cannot open file to receive\015\012");
  1381.                     return(-1);
  1382.                 } else ftpfh = 12;
  1383. #else
  1384.  
  1385.                 if (0 > (ftpfh = creat(&name2[0],ftpfilemode))) {
  1386.                     putstring(ftpscrn,"Cannot open file to receive\015\012");
  1387.                     return(-1);
  1388.                 }
  1389. #endif
  1390.  
  1391.         } else {
  1392. #ifdef MACBINARY
  1393.                 if ((ftp_mbfp = MBopen(&name[0], defaultv, MB_WRITE +    /* BYU 2.4.18 */
  1394.                     (((!MacBinary) || (ftpfilemode == FAMODE)) ? MB_DISABLE : 0
  1395.                     ))) == 0L) {
  1396.                     putstring(ftpscrn,"Cannot open file to receive\015\012");
  1397.                     return(-1);
  1398.                 } else ftpfh = 12;
  1399. #else
  1400.  
  1401.                 if (0 > (ftpfh = creat(&name[0],ftpfilemode))) {
  1402.                     putstring(ftpscrn,"Cannot open file to receive\015\012");
  1403.                     return(-1);
  1404.                 }
  1405. #endif
  1406.         }
  1407.  
  1408.         strcpy(&commandbuf[5],name);            /* Put remote name back into command */
  1409.  
  1410.         ftpport(ftpscrn);        /* open data connection */
  1411.         screens[ftpscrn].ftpstate = 2;
  1412.         screens[ftpscrn].ftpnext = 30;
  1413.         strcpy(screens[ftpscrn].ftpbuf,commandbuf);
  1414.         strcat(screens[ftpscrn].ftpbuf,"\015\012");
  1415.         return(1);
  1416.  
  1417.     } else if (!strncmp(commandbuf,"LIST",4) || !strncmp(commandbuf,"NLST",4)) {
  1418.  
  1419.         if ((screens[ftpscrn].clientflags & CAPTURE_DATA) != 0)
  1420.             screens[ftpscrn].capturesize = 0;        /* Size of captured data */
  1421.  
  1422.         ftpport(ftpscrn);        /* data connection */
  1423.         screens[ftpscrn].ftpstate = 2;
  1424.         screens[ftpscrn].ftpnext = 40;
  1425.         strcpy(screens[ftpscrn].ftpbuf,commandbuf);
  1426.         strcat(screens[ftpscrn].ftpbuf,"\015\012");
  1427.         return(1);
  1428.  
  1429.     } else if (!strncmp(commandbuf,"TYPE",4)) {
  1430.         if (toupper(commandbuf[5]) == 'I')
  1431.             ftpfilemode = FIMAGE;                /* Remember mode */
  1432.         else if (toupper(commandbuf[5]) == 'A')
  1433.             ftpfilemode = FASCII;
  1434.  
  1435.     }
  1436.  
  1437.     netpush(screens[ftpscrn].port);
  1438.  
  1439.     strcat(commandbuf,"\015\012");                                    /* BYU 2.4.11 */
  1440.     netwrite(screens[ftpscrn].port,commandbuf,strlen(commandbuf));    /* BYU 2.4.11 - send command */
  1441.  
  1442.     if (((screens[ftpscrn].clientflags & CAPTURE_DATA) == 0) && ofile[0]) {        /* command redirected */
  1443.         if ((screens[ftpscrn].ftpstate != 20) && (screens[ftpscrn].ftpstate != 30)) {    /* not get or put */
  1444.             if (0 > (ftpfh = ftpopen(ofile)))
  1445.                 nputs(" Cannot open output file.");
  1446.             else if (ftpdata > -1) {
  1447.                 screens[ftpscrn].ftpstate = 30;    /* act as get, since data goes into file */
  1448.             } else {
  1449.                 close(ftpfh);
  1450.                 ftpfh = 0;
  1451.             }
  1452.         }
  1453.     }
  1454. #if 0
  1455. if (debug) {
  1456.     sprintf(printline,"---> %s",commandbuf);    /* show command sent */
  1457.     nputs(printline);
  1458. }
  1459. #endif
  1460.     return(FALSE);
  1461. }
  1462.  
  1463.  
  1464. /************************************************************************/
  1465. /* userftpd
  1466. *  FTP receive and send file functions
  1467. /************************************************************************/
  1468.  
  1469. userftpd(code,myport) int code,myport; {
  1470.     Boolean needanswer;
  1471.     long mytime;
  1472.     int cmd_status,connection_status,ftpstate,i,mycode,myftpdata,mytelport,mywindow;
  1473.     char command[MAXFTP],printline[MAXFTP],word[MAXFTP];
  1474. #if 0
  1475.     char answer[20];
  1476. #endif
  1477.  
  1478.     mycode = code;
  1479.  
  1480.     connection_status = 0;        /* BYU 2.4.12 - assume good connection status */
  1481.     ftpstate = 1;
  1482.     mywindow = WindByPort(myport);
  1483.     if (mywindow >= 0) {
  1484.       if (myport == screens[mywindow].port) {
  1485.         ftpstate = screens[mywindow].ftpstate;
  1486.         myftpdata = -1;
  1487.       } else {
  1488.         ftpstate = screens[mywindow].ftpstate;
  1489.         myftpdata = screens[mywindow].ftpport;
  1490.     } }
  1491.  
  1492.     if (mywindow < 0) return(0);
  1493. #if 0
  1494. if (debug) {
  1495.     sprintf(printline,"  %d %d %u twin: %d\015\012",ftpstate,mycode,myport,mywindow);
  1496.     putstring(mywindow,printline);
  1497. }
  1498. #endif
  1499.  
  1500.     mytelport = screens[mywindow].port;
  1501.  
  1502.     switch (ftpstate) {
  1503.         default:    /* unknown */
  1504.             break;
  1505.  
  1506.         case 1:
  1507.             if ((mycode == CONDATA) && (myport == mytelport)) 
  1508.                 connection_status = dumpcon(myport,mywindow);
  1509.             break;
  1510.  
  1511. /* Wait for response from "PORT" command, then send ftp command */
  1512.         case 2:
  1513.             if (mycode == CONDATA) {
  1514.                 connection_status = dumpcon(myport,mywindow);
  1515.                 netpush(screens[mywindow].port);
  1516.                 netwrite(screens[mywindow].port,screens[mywindow].ftpbuf,strlen(screens[mywindow].ftpbuf));    /* send command */
  1517.                 screens[mywindow].ftpstate = screens[mywindow].ftpnext;
  1518. #if 0
  1519. if (debug) {
  1520.     sprintf(printline,"---> %s",screens[mywindow].ftpbuf);    /* show command sent */
  1521.     nputs(printline);
  1522. }
  1523. #endif
  1524.             }
  1525.             break;
  1526.  
  1527. /* Wait for response from "TYPE" command, then send ftp command */
  1528.         case 3:
  1529.             if (mycode == CONDATA) {
  1530.                 connection_status = dumpcon(myport,mywindow);
  1531.                 cmd_status = ftpdo(mywindow,screens[mywindow].ftpbuf,"");
  1532. #if 0
  1533. if (debug) {
  1534.     sprintf(printline,"---> %s",screens[mywindow].ftpbuf);    /* show command sent */
  1535.     nputs(printline);
  1536. }
  1537. #endif
  1538.             }
  1539.             break;
  1540.  
  1541.         case 5:
  1542. /* Get the next file of an MGET. */
  1543.             if ((screens[mywindow].clientflags & CAPTURE_DATA) != 0) {
  1544.                 screens[mywindow].clientflags &= ~CAPTURE_DATA;
  1545.             }
  1546.  
  1547. /* After capturing the data, initiate the file transfer(s) */
  1548.             if ((screens[mywindow].clientflags & MGET_STATE) != 0) {
  1549.                 if (screens[mywindow].capturesize > 0) {
  1550.                     screens[mywindow].ftpstate = 6;
  1551.                     netputuev(CONCLASS,CONDATA,mytelport);    /* Stay alive to transfer file */
  1552.                 } else {
  1553.                     screens[mywindow].clientflags &= ~MGET_STATE;
  1554.                     screens[mywindow].ftpstate = 1;
  1555.             }    }
  1556.             break;
  1557.  
  1558. /* Receive one MGET file. */
  1559.         case 6:
  1560.             connection_status = dumpcon(myport,mywindow);
  1561.             if (getnname(captlist,word)) {    /* for each name */
  1562. #if 0
  1563.                 if (prompt) {    /* check */
  1564.                     sprintf(printline,"mget %s? ",word);
  1565.                     putstring(mywindow,printline);
  1566.                     if (ftpgets(answer,20,1)==ABORT) {    /* abort */
  1567.                         command[0] = '\0';    /* no more processing */
  1568.                         break;            /* quit immediately */
  1569.                     }
  1570.                     if (tolower(*(stpblkp(answer)))!='y') continue;
  1571.                 } else {
  1572. #endif
  1573.                     sprintf(printline,"Receiving %s\015\013",word);
  1574.                     putstring(mywindow,printline);
  1575. #if 0
  1576.                 }
  1577. #endif
  1578.                 sprintf(command,"RETR \"%s\"",word);
  1579.                 if ((cmd_status = ftpdo(mywindow,command,"")) < 0) {
  1580.                     screens[mywindow].clientflags &= ~MGET_STATE;
  1581.                     screens[mywindow].ftpstate = 1;
  1582.                 }
  1583.             } else {
  1584.                 screens[mywindow].clientflags &= ~MGET_STATE;
  1585.                 screens[mywindow].ftpstate = 1;
  1586.             }
  1587.             break;
  1588.  
  1589. /* Send a file to the remote connection */
  1590.         case 20:
  1591.  
  1592.             if (mycode == CONFAIL) mycode = CONCLOSE;    /* something went wrong */
  1593.  
  1594.             if (mycode == CONOPEN) {
  1595.                 screens[mywindow].ftpstate = 21;
  1596.                 transtime = TickCount();
  1597.                 translen = 0;
  1598.                 towrite = 0;
  1599.                 xp = 0;
  1600.                 netputuev(CONCLASS,CONDATA,myport);
  1601.             } else if ((mycode == CONDATA) && (myport == mytelport)) {
  1602.               connection_status = dumpcon(myport,mywindow);
  1603.             }
  1604.             break;
  1605.  
  1606.         case 21:
  1607. /*
  1608. *  transfer file(s) to the other host via ftp request
  1609. *  file is already open = ftpfh
  1610. */
  1611.             if (mycode == CONDATA) {
  1612.               if (myport == mytelport) {
  1613.                     connection_status = dumpcon(myport,mywindow);
  1614.               } else if (myport == myftpdata) {
  1615.  
  1616.                 netputuev(CONCLASS,CONDATA,myport);        /* Stay alive */
  1617.  
  1618.                 if (towrite <= xp) {
  1619.  
  1620.                     i = BUFFERS;
  1621. #ifdef MACBINARY
  1622.                     towrite = MBread( ftp_mbfp, xs, i);
  1623. #else
  1624. /*                    towrite = read(ftpfh,xs,i);    /*  */
  1625.                     towrite = BUFFERS;
  1626.                     FSRead(ftpfh,&towrite,&xs[0]);
  1627. #endif
  1628.                     xp = 0;
  1629.                 }
  1630.  
  1631.                 if ((towrite <= 0) || netest(myftpdata)) {        /* we are done */
  1632.                     if (ftp_mbfp->fd != 0) MBclose( ftp_mbfp );        /* BYU - close input file */
  1633.                     screens[mywindow].ftpstate = 22;
  1634.                     break;
  1635.                 }
  1636.  
  1637.                 if (ftpfilemode == FAMODE)
  1638.                     i = Sfwrite(myftpdata,&xs[xp],(int) towrite-xp);
  1639.                 else
  1640.                     i = netwrite(myftpdata,&xs[xp],(int) towrite-xp);
  1641.  
  1642.                 if (i > 0) {
  1643.                     xp += i;
  1644.                     translen += i;
  1645.                 }
  1646.  
  1647.                 mytime = TickCount();
  1648.                 if ((transtime + 800) < mytime) {
  1649.                     transtime = mytime;
  1650.                     sprintf(printline,"%ld/%ld bytes sent.\015\013",translen,filelen);
  1651.                     i = strlen(printline);
  1652.                     parse( &screens[mywindow],&printline[0],i);
  1653.                 }
  1654.               }
  1655.             }
  1656.  
  1657.             break;
  1658.  
  1659.         case 22:                            /* wait for data to be accepted */
  1660.             netputuev(CONCLASS,CONDATA,myport);        /* Stay alive */
  1661.  
  1662.             fcnt = netpush(myftpdata);        /* will go negative on err */
  1663.             if (!fcnt || netest(myftpdata)) {
  1664.                 mycode = CONCLOSE;
  1665.                 sprintf(printline,"%ld/%ld bytes sent.\015\013",translen,filelen);
  1666.                 parse( &screens[mywindow],&printline[0],strlen(printline));
  1667.             }
  1668.             if ((mycode == CONDATA) && (myport == mytelport)) 
  1669.                 connection_status = dumpcon(myport,mywindow);
  1670.             break;
  1671.  
  1672. /* Get a file from the remote connection */
  1673.         case 30:
  1674.             if (mycode == CONFAIL) mycode = CONCLOSE;    /* something went wrong */
  1675.  
  1676.             if (mycode == CONOPEN) {
  1677.                 screens[mywindow].ftpstate = 31;
  1678.                 filelen = xp = 0;
  1679.                 transtime = TickCount();
  1680.                 translen = 0L;
  1681.             } else if ((mycode == CONDATA) && (myport == mytelport)) {
  1682.               connection_status = dumpcon(myport,mywindow);
  1683.             }
  1684.             break;
  1685.  
  1686. /*
  1687. * file has already been opened, take everything from the connection
  1688. * and place into the open file: ftpfh
  1689. */
  1690.         case 31:
  1691.             if (mycode == CONDATA) {
  1692.               if (myport == mytelport) {
  1693.                     connection_status = dumpcon(myport,mywindow);
  1694.               } else if (myport == myftpdata) {
  1695.  
  1696. /* wait until xs is full before writing to disk */
  1697.                 if (filelen <= 2000) {
  1698.  
  1699.                     if (xp) {
  1700. #ifdef MACBINARY
  1701.                         if (0 > MBwrite(ftp_mbfp, xs, xp))
  1702.                             mycode = CONCLOSE;
  1703. #else
  1704.                         if (0 > write(ftpfh,xs,xp))        /* disk full err */
  1705.                             mycode = CONCLOSE;
  1706. #endif
  1707.                       xp = 0;
  1708.                     }
  1709.                     filelen = BUFFERS;        /* expected or desired len to go */
  1710.                 }
  1711.  
  1712.                 if (mycode == CONDATA) {
  1713.                     if (ftpfilemode == FAMODE)
  1714.                         fcnt = Sfread(myftpdata,&xs[xp],(int)filelen);
  1715.                     else
  1716.                         fcnt = netread(myftpdata,&xs[xp],(int)filelen);
  1717.  
  1718.                     if (fcnt >= 0) {
  1719.                         filelen -= fcnt;
  1720.                         xp += fcnt;
  1721.                         translen += fcnt;
  1722.                     }
  1723.  
  1724.                     mytime = TickCount();
  1725.                     if ((transtime + 800) < mytime) {
  1726.                         transtime = mytime;
  1727.                         if ((screens[mywindow].clientflags & MGET_STATE) == 0) {
  1728.                             sprintf(printline,"%ld bytes received.\015\013",translen);
  1729.                             i = strlen(printline);
  1730.                             parse( &screens[mywindow],&printline[0],i);
  1731.                     }    }
  1732.  
  1733. /*                    printf(" %d %d %d \012",filelen,xp,fcnt);
  1734.                     n_row();  
  1735. */
  1736.                     if (fcnt < 0) {
  1737. #ifdef MACBINARY
  1738.                         if (0 > MBwrite( ftp_mbfp, xs, xp)) {
  1739.                             break;
  1740.                         }
  1741.                         if (ftp_mbfp->fd != 0) {
  1742.                             MBclose( ftp_mbfp );
  1743.                         }
  1744. #else
  1745.                         if (0 > write(ftpfh,xs,xp)) { /* disk full check */
  1746.                             break;
  1747.                         }
  1748.                         close(ftpfh);
  1749. #endif
  1750.                           ftpfh = 0;
  1751.                     }
  1752.                     netputuev(CONCLASS,CONDATA,myport);
  1753.                 }
  1754.               }
  1755.             }
  1756. /* Ouput any remaining data before closing */
  1757.             if (mycode == CONCLOSE) {
  1758.                 if (xp) {
  1759. #ifdef MACBINARY
  1760.                     if (0 > MBwrite(ftp_mbfp, xs, xp))
  1761.                         netclose(myftpdata);
  1762. #else
  1763.                     if (0 > write(ftpfh,xs,xp))        /* disk full err */
  1764.                         netclose(myftpdata);
  1765. #endif
  1766.                 }
  1767.                 if ((screens[mywindow].clientflags & MGET_STATE) == 0) {
  1768.                     sprintf(printline,"%ld bytes received.\015\013",translen);
  1769.                     i = strlen(printline);
  1770.                     parse( &screens[mywindow],&printline[0],i);
  1771.             }    }
  1772.             break;
  1773.  
  1774. /* Waiting for "ftpdata" connection to open, display any communication 
  1775.    from the telnet port. */
  1776.         case 40:
  1777.             if (mycode == CONOPEN) 
  1778.                 screens[mywindow].ftpstate = 41;
  1779.  
  1780.             if ((myport == myftpdata) &&
  1781.                 ((screens[mywindow].clientflags & CAPTURE_DATA) != 0)) {
  1782.                 captcon(myport,mywindow);
  1783.             } else {
  1784.                 connection_status = dumpcon(myport,mywindow);
  1785.             }
  1786.             break;
  1787.  
  1788. /* If the "ftpdata" port is open, then postpone reading and displaying 
  1789.    any data from other ports once data has been received.  Otherwise, 
  1790.    read and display data from anywhere. */
  1791.         case 41:
  1792.             if (mycode == CONDATA) {
  1793.                 if ((myport == myftpdata) &&
  1794.                     ((screens[mywindow].clientflags & CAPTURE_DATA) != 0)) {
  1795.                     captcon(myport,mywindow);
  1796.                 } else {
  1797.                     connection_status = dumpcon(myport,mywindow);
  1798.                 }
  1799.                 if (myport == myftpdata) screens[mywindow].ftpstate = 42;
  1800.                 netputuev(CONCLASS,CONDATA,myport);
  1801.             } else if (mycode == CONCLOSE) {
  1802.                 screens[mywindow].ftpstate = 40;
  1803.             }
  1804.             break;
  1805.  
  1806. /* Only data from "ftpdata" */
  1807.         case 42:
  1808.             if (mycode == CONDATA) {
  1809.                 if (myport == myftpdata) {
  1810.                     if ((screens[mywindow].clientflags & CAPTURE_DATA) != 0) {
  1811.                         captcon(myport,mywindow);
  1812.                     } else {
  1813.                         connection_status = dumpcon(myport,mywindow);
  1814.                 }    }
  1815.                 netputuev(CONCLASS,CONDATA,myport);            /* Keep port monitoring alive */
  1816.             } else if (mycode == CONCLOSE) {
  1817.                 screens[mywindow].ftpstate = 40;
  1818.             }
  1819.             break;
  1820.  
  1821.     }  /* end of switch */
  1822.  
  1823. /*
  1824. *  After reading from connection, if the connection is closed,
  1825. *  reset up shop.
  1826. */
  1827.     if ((mycode == CONCLOSE) || (connection_status < 0)) {        /* BYU 2.4.12 */
  1828.         if (connection_status < 0)                                /* BYU 2.4.12 */
  1829.             screens[mywindow].clientflags &= ~MPUT_STATE;
  1830.         if (ftpfh > 0) {
  1831.             close(ftpfh);
  1832.             ftpfh = 0;
  1833.         }
  1834.         if (ftp_mbfp->fd != 0) MBclose( ftp_mbfp );
  1835.         screens[mywindow].ftpstate = 1;
  1836.         fcnt = 0;
  1837.         if (myftpdata == myport) {
  1838.             netclose(myftpdata);
  1839.             Sptypes[myftpdata] = -1;
  1840.             screens[mywindow].ftpport = -1;
  1841.         }
  1842.         if ((screens[mywindow].clientflags & TYPE_I_ON_CLOSE) != 0) {
  1843.             screens[mywindow].clientflags = 0;
  1844.             cmd_status = ftpdo(mywindow,"TYPE I","");
  1845.         }
  1846.  
  1847. /* Send the next file of an MPUT */
  1848.         if ((screens[mywindow].clientflags & MPUT_STATE) != 0) {
  1849.             needanswer = TRUE;
  1850.             while (needanswer) {
  1851.                 needanswer = FALSE;
  1852.                 if (glob) {                                /* local wildcard expansion */
  1853.                     newfile = nextname(transfile);        /* get next name */
  1854.                     if (newfile == NULL) {                /* if no expansions yet */
  1855.                         if (getword(captlist,transfile)) {
  1856.                             newfile = firstname(transfile);    /* get first name */
  1857.                             if (newfile == NULL) {            /* if no expansions */
  1858.                                 sprintf(printline,"No match for %s",transfile);
  1859.                                 nputs(printline);
  1860.                     }    }    }
  1861.                 } else if (getword(captlist,transfile)) {
  1862.                     newfile = transfile;
  1863.                 } else newfile = NULL;
  1864.  
  1865.                 if (newfile == NULL) {
  1866.                     screens[mywindow].clientflags &= ~MPUT_STATE;
  1867.                     screens[mywindow].ftpstate = 1;
  1868.                 } else {
  1869. #if 1    /* When prompting is fixed switch to the code below */
  1870.                     sprintf(screens[mywindow].ftpbuf,"STOR \"%s\"",newfile);
  1871.                     cmd_status = ftpdo(mywindow,screens[mywindow].ftpbuf,"");
  1872. #else
  1873.                     if (prompt) {                            /* check */
  1874.                         sprintf(printline,"mput %s? ",newfile);
  1875.                         putstring(mywindow,printline);
  1876.                         if (ftpgets(answer,20,1) == ABORT) {    /* abort */
  1877.                             screens[mywindow].clientflags &= ~MPUT_STATE;
  1878.                             screens[mywindow].ftpstate = 1;
  1879.                         } else if (tolower(*(stpblkp(answer))) != 'y') {
  1880.                             needanswer = TRUE;
  1881.                         } else {
  1882.                             sprintf(screens[mywindow].ftpbuf,"STOR \"%s\"",newfile);
  1883.                             cmd_status = ftpdo(mywindow,screens[mywindow].ftpbuf,"");
  1884.                         }
  1885.                     } else {
  1886. /* The Mac file may have special characters, so quote the whole thing */
  1887.                         sprintf(screens[mywindow].ftpbuf,"STOR \"%s\"",newfile);
  1888.                         cmd_status = ftpdo(mywindow,screens[mywindow].ftpbuf,"");
  1889.                     }
  1890. #endif
  1891.          }    }    }
  1892.  
  1893.         if ((screens[mywindow].clientflags & MGET_STATE) != 0) {
  1894.             screens[mywindow].ftpstate = 5;            /* BYU 3 */
  1895.             netputuev(CONCLASS,CONDATA,mytelport);    /* BYU 3 - Stay alive to transfer file */
  1896.         }
  1897.     }
  1898.     return(TRUE);
  1899. }
  1900.  
  1901.  
  1902. #if 0
  1903. /************************************************************************/
  1904. /* getdir: get current directory.  Finds current drive and current path
  1905. * on drive, returns a string.
  1906. *
  1907. /************************************************************************/
  1908.  
  1909. getdir(drive,path) int drive; char *path; {
  1910. char partpath[64];
  1911.  
  1912. if (!drive) drive = getdsk();    /* current disk */
  1913. getcd(drive+1,partpath);    /* current dir */
  1914. sprintf(path,"%c:\\%s",'A'+drive,partpath);
  1915. return(TRUE);
  1916. }
  1917.  
  1918.  
  1919. finduniq(name,list,listsize) char *name, *list[]; int listsize; {
  1920. int i,j=NONE,len;
  1921.  
  1922. len = strlen(name);
  1923. for (i=0; i<listsize; i++) {
  1924.     if (!strncmp(name,list[i],len)) {        /* prefix */
  1925.     if (len==strlen(list[i])) return(i+1);    /* exact match */
  1926.     if (j!=NONE) j = AMBIGUOUS;    /* more than one match */
  1927.     else j = i+1;            /* note prefix found */
  1928.     }
  1929. }
  1930. return(j);            /* prefix */
  1931. }
  1932. #endif
  1933.  
  1934.  
  1935. /***************************************************************************/
  1936. /*  dosescape
  1937. *  escape to dos for processing
  1938. *  put the connections to automated sleep while in DOS
  1939. /************************************************************************/
  1940.  
  1941. dosescape() {
  1942.  
  1943. #if 0
  1944.     int i;
  1945.     nputs("Warning, some programs will interfere with network communication and can");
  1946.     nputs("cause lost connections.  Do not run any network programs from this DOS shell.");
  1947.     nputs("Type 'EXIT' to return to FTP");
  1948. /*
  1949. *  invoke a put-to-sleep routine which calls netsleep every 8/18ths of a sec
  1950. */
  1951.  
  1952.     tinst();
  1953.     i = system("command");        /* call DOS */
  1954.     tdeinst();
  1955.  
  1956.     if (i < 0) {
  1957.         nputs("\012\012Error loading COMMAND.COM");
  1958.         nputs("Make sure COMMAND.COM is specified under COMSPEC.");
  1959.         nputs("It must also be in a directory which is in your PATH statement.");
  1960.     }
  1961.  
  1962. /*    if (fromtty) n_row();    /*  */
  1963. #endif
  1964.     return(0);
  1965. }
  1966.  
  1967. #if 0
  1968. static int scrsetup;
  1969.  
  1970. nputs(line) char *line; {
  1971. if (!scrsetup) {
  1972.     scrsetup = 1;
  1973.     if (fromtty) {
  1974.         n_clear();            /* clear screen */
  1975.         n_wrap(1);            /* cursor positioning */
  1976.         n_cur(0,0);
  1977.         n_color(2);            /* set color to green */
  1978.     }
  1979.  
  1980.     nputs("             National Center for Supercomputing Applications");
  1981.     nputs("                      FTP version 1.04  7/5/88\012");
  1982. }
  1983. if (fromtty) n_puts(line);
  1984. else puts(line);
  1985. return(TRUE);
  1986. }
  1987. #endif